import threading
import time
import traceback
from datetime import datetime

import pyautogui
import win32gui

import src.img as imgtool
import cv2
from PyQt5.QtCore import Qt
from PyQt5.QtGui import *
from PyQt5.QtWidgets import *

import py_base.tools.qt as QtTool

from py_base.tools import img as baseImgTool, win32 as win32tool
from py_base.window_base import WinBase
from src import enum, sub_win

end_tmp_img = cv2.imread("asset/end_tmp.jpg")


class Gui(WinBase):
    def __init__(self):
        WinBase.__init__(self)

        self.setWindowTitle('找茬工具')

        self.addRow(QLabel(enum.TEXT_EXPLAIN))
        self.button = self.addBtn(enum.TEXT_BTN, self.handelBeginBtn)
        self.addBtn("关闭圆圈窗口", self.closeSubWin)

        self.addRow(QtTool.createQCheckBox("自动点击"), field="autoClick")
        self.addRow(QtTool.createQCheckBox("自动找下一张"), field="autoNext")
        self.add2Btn("测试", "保存截图", self.testFunc, self.saveFunc)

        self.image = QLabel("初步解析1")
        self.image.setAlignment(Qt.AlignCenter)
        self.vbox.addWidget(self.image)

        self.image1 = QLabel("二值化图")
        self.image1.setAlignment(Qt.AlignCenter)
        self.vbox.addWidget(self.image1)

        self.setLayout(self.vbox)

        self.subWin = sub_win.ChildWin()
        self.subWin.hide()

        self.btnPos = [0, 0]  # 完成一张图后，将鼠标挪走，避免自动识别下一张时有鼠标在图片里面形成干扰

        self.autoFinding = False  # 是否正在找结束标识，自动识别下一张
        self.autoClicking = False  # 是否正在自动点击

        self.thread_index = 1  # 线程序号，调试用
        self.imgCut = None  # 截图的副本
        self.hwnd = None  # 游戏窗口句柄

        self.initSetting()

    def handelBeginBtn(self):
        try:
            # 保存鼠标位置，用于自动点击下一次查找
            x, y = pyautogui.position()
            self.btnPos = [x, y]

            self.subWin.text = ''
            self.subWin.hide()

            self.button.setText(enum.TEXT_BTN)
            self.hwnd = win32tool.findWindows(enum.WIN_TITLE)
            if self.hwnd is None:
                raise Exception("找不到窗口")

            img, hwnd = baseImgTool.getScreenshot(self.hwnd)
            self.imgCut = img.copy()
            diffImg, diffImg1, dots = imgtool.diffImg(img)

            pix = baseImgTool.cvImg2QImage(diffImg)
            self.image.setPixmap(QPixmap.fromImage(pix))

            pix = baseImgTool.cvImg2QImage(diffImg1)
            self.image1.setPixmap(QPixmap.fromImage(pix))

            self.button.setText("找到个数" + str(len(dots)))

            self.showSubWin(hwnd, dots)

            # 开启新线程执行自动点击，否则会影响点的绘制
            if enum.setting['autoClick']:
                threading.Thread(target=self.autoClick, args=(hwnd, dots)).start()

            if enum.setting['autoNext']:
                self.autoEnd()  # 开启点击的同时，启动结束界面的检测，自动启动下一个图片的识别

        except Exception as e:
            print('str(Exception):\t', str(Exception))
            print('traceback.print_exc():')
            traceback.print_exc()
            print('traceback.format_exc():\n%s' % traceback.format_exc())
            self.button.setText(str(e))
            return

    def showSubWin(self, hwnd, dots):
        dpi = win32tool.getDpi()
        new_dots = []
        for v in dots:
            new_dots.append([v[0] * dpi, v[1] * dpi])

        self.subWin.dots = new_dots
        left, top, right, bottom = win32gui.GetWindowRect(hwnd)
        self.subWin.setGeometry(left, top, right - left, bottom - top)
        self.subWin.dpi = dpi
        self.subWin.show()

    def closeSubWin(self):
        self.subWin.hide()

    def autoClick(self, hwnd, dots):
        if self.autoClicking:
            print("点击冲突")
            return
        self.autoClicking = True

        left, top, right, bottom = win32gui.GetWindowRect(hwnd)
        dpi = win32tool.getDpi()
        new_dots = []
        for v in dots:
            new_dots.append([left + int(v[0] * dpi), top + int(v[1] * dpi)])

        if len(new_dots) == 5:
            for v in new_dots:
                pyautogui.click(v[0], v[1])

        else:
            # 点数不止5个，离得近的按钮不重复点击
            not_click = []
            for k, v in enumerate(new_dots):
                if k in not_click:
                    continue
                pyautogui.click(v[0], v[1])

                for ki, vi in enumerate(new_dots):
                    # 按下一个位置，检查剩余位置有没有跟自己离得很近的
                    if ki == k:
                        continue
                    diff = pow(abs(v[0] - vi[0]), 2) + pow(abs(v[1] - vi[1]), 2)
                    max_diff = 100
                    if diff < pow(max_diff, 2) * dpi:
                        not_click.append(ki)
        self.autoClicking = False


    def autoEnd(self):
        tIndex = self.thread_index
        self.thread_index += 1
        if self.autoFinding:
            print("查找ending冲突", tIndex)
            return
        self.autoFinding = True

        def do():
            while True:
                time.sleep(0.1)

                if not self.isVisible():
                    print("退出查找循环", tIndex)
                    self.autoFinding = False
                    return
                if not win32gui.IsWindow(self.hwnd):
                    print("窗口已经关闭", tIndex)
                    return

                image, hwnd = baseImgTool.getScreenshot(self.hwnd)
                image = cv2.cvtColor(image, cv2.COLOR_BGR2RGB)
                image = cv2.cvtColor(image, cv2.COLOR_RGB2BGR)
                result = cv2.matchTemplate(image, end_tmp_img, cv2.TM_CCOEFF_NORMED)
                (minVal, maxVal, minLoc, maxLoc) = cv2.minMaxLoc(result)

                if maxVal > 0.9:
                    pyautogui.moveTo(self.btnPos[0], self.btnPos[1])
                    self.subWin.text = "下一张图自动开始"
                    self.subWin.hide()
                    self.subWin.show()
                    time.sleep(3)
                    self.autoFinding = False
                    self.handelBeginBtn()  # 这里调用完后，又会开启一个新的线程进行结束事件识别，执行完后，本线程退出
                    return

        threading.Thread(target=do).start()

    def saveFunc(self):

        if self.imgCut is not None:
            now = datetime.now()
            formatted_time = now.strftime("%Y-%m-%d %H-%M-%S")
            cv2.imwrite(enum.OUTPUT_DIR + ("cut/%s.jpg" % formatted_time), self.imgCut)
            self.button.setText('图片已保存')

    def testFunc(self):
        print(enum.setting['autoClick'])
        print(enum.setting['autoNext'])
        return
        try:
            global end_tmp_img
            image, hwnd = baseImgTool.getScreenshot(self.hwnd)
            image = cv2.cvtColor(image, cv2.COLOR_BGR2RGB)
            image = cv2.cvtColor(image, cv2.COLOR_RGB2BGR)
            cv2.imshow("c", image)

            cv2.imshow("c1", end_tmp_img)

            result = cv2.matchTemplate(image, end_tmp_img, cv2.TM_CCOEFF_NORMED)
            (minVal, maxVal, minLoc, maxLoc) = cv2.minMaxLoc(result)
            print(minVal, maxVal, minLoc, maxLoc)
            return
        except Exception as e:
            print('str(Exception):\t', str(Exception))
            print('traceback.print_exc():')
            traceback.print_exc()
            print('traceback.format_exc():\n%s' % traceback.format_exc())
            self.button.setText(str(e))
            return
